package com.example.gulimall.order.config;

import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

@Configuration
public class MyRabbitConfig {
    @Autowired
    RabbitTemplate rabbitTemplate;
    @Bean
    public MessageConverter messageConverter(){
        return  new Jackson2JsonMessageConverter();
    }
    /**
     * 定制rabbitTemplate;
         * 1 服务器收到消息，
              * 1 spring.rabbitmq.publisher-confirms=true,
              * 2 设置确认回调setConfirmCallback
         * 2 消息正确抵达队列回调
             * #开启发送消息抵达队列的确认
             * spring.rabbitmq.publisher-returns=true
             * # 只要抵达队列，以异步的方式优先回调我们这个returnconfirm
             * spring.rabbitmq.template.mandatory=true
             * 设置确认回调  setReturnCallback
        * 3 消费端确认（保证每个消息被正确消费，此时才可以在服务器删除这个消息）
            * 1 默认自动确认，只要消息接收到，客户端会自动确认，服务端就会移除这个消息
         *          问题： 我们收到很多消息，地洞回复给服务器ack,只有一个消息处理成功了，
         *          客户端就宕机了，剩下的其他消息就丢失了
     *        2 消费者手动确认 spring.rabbitmq.listener.simple.acknowledge-mode=manual
     *              1 只要我们没有确认，消息就一直是unacked状态，即使Consumer宕机，消息不会丢失，会重新变成Ready状态
     *                下一次继续放回队列，消费
     *              2   channel.basicAck(deliveryTag,false); 签收： 签收的消息标签，是否批量签收 true批量签收
     *              3  channel.basicNack(deliveryTag,false,false); 拒签：签收的消息标签 true 批量拒签， 是否批量签收，是否重新入队 true 重新入队
     *
     *
     */
    @PostConstruct //MyRabbitConfig对象创建完成后，执行这个方法；
    public  void  initRabbitTemplate(){
        // 设置发送端确认
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            /***
             *
             * @param correlationData 当前消息的 唯一关联数据（这个是消息的唯一id）
             * @param b 消息服务端是否收到,只要抵达服务器，就是true
             * @param s 失败的原因
             */
            @Override
            public void confirm(CorrelationData correlationData, boolean b, String s) {
                System.out.println("CorrelationData....["+correlationData+"]==>b["+b+"]===>s["+s+"]");
            }
        });
        // 设置消息抵达队列的确认回调,
        rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
            /**
             * 只要没有投递给指定的队列，就触发这个失败的回调
             * @param message 投递失败的消息详细信息
             * @param i 回复的状态码
             * @param s 回复的文本内容
             * @param s1 当时这个消息发给哪个交换机
             * @param s2  当时这个消息用哪个路由键
             */
            @Override
            public void returnedMessage(Message message, int i, String s, String s1, String s2) {
                System.out.println("Fail Message+["+message+"]"+"Fail i+["+i+"]"+"Fail s+["+s1+"]"+"Fail Message+["+s2+"]");
            }
        });
    }

}

